﻿//#include "eval.h"
#include "global.h"
//#include "interp.h"
#include "mem.h"
#include "vm/chunk.h"
#include "vm/debug.h"
#include "vm/vm.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//原始版本有多种模式,一个程序
//当有2个参数 模式是命令行 解释模式
//   第一个参数 有 --tree-walk  --vm --help
//              或者 都不是 ,那么就是模式4  参数1 就是要执行的脚本文件名字
//当有4--N个参数报告错误
//当有3个参数 是非交互模式 参数1--tree-walk  --vm --help 参数 2 是脚本程序文件名
// 拆分出来 
//这是没有 --tree-walk  的 vm + file 模式

//例子  runvm.exe 1.lox

typedef enum {
    MODE_TREEWALK,
    MODE_VM
} Mode;

typedef struct runnable_mode {
    Mode mode;
    void (*codeRunner)(const char* code);
} RunnableMode;

 
char* read_line(const char* prompt);
char* read_file(const char* filepath);

void run_treewalk_chunk(const char* code);
//no void run_treewalk_file(const char* code);
void run_vm_chunk(const char* code);
void run_vm_file(const char* code);
void vm_chunk_test();
 

int main(int argc, const char* argv[])
{
#ifdef _WIN32
    char separator = '\\';
#else
    char separator = '/';
#endif
    char* name = strrchr(argv[0], separator);
    char* line = NULL;
    char* buf = NULL;
#define ERROR_MSG_MAXLEN 1024
	char errorbuff[ERROR_MSG_MAXLEN];
    RunnableMode mode;
 
    ////printf("debug1 %d  ",values.error );
    
    name = name != NULL ? name + 1 : name;

  
    //printf("debug2");

     //printf("debug3");
    mode.mode =  MODE_VM;
    
    buf = read_file(argv[1]);
    if (buf == NULL) {
		#ifdef _WIN32
		strerror_s(errorbuff,ERROR_MSG_MAXLEN,errno);
		#else
		strerror_r(errno,errorbuff,ERROR_MSG_MAXLEN);
	    #endif 
        fprintf(stderr, "%s\n", errorbuff);
        exit(74);
    } else {
        mode.codeRunner =   run_vm_file;
        mode.codeRunner(buf);
    }
    fr(buf);

     //printf("debug4");
    return EXIT_SUCCESS;
}

 

char* read_file(const char* filepath)
{
    size_t readBytes = 0, length = 0;
    char* buf = NULL;
    FILE* fp = fopen(filepath, "rb");

    if (fp == NULL) {
        fprintf(stderr, "Cannot open file %s\n", filepath);
        return NULL;
    }

    if (!fseek(fp, SEEK_SET, SEEK_END)) {
        length = ftell(fp);
        rewind(fp);
    }

    buf = (char*)malloc(length + 1);
    if (buf == NULL) {
        fprintf(stderr, "No enough memory to read file: %s\n", filepath);
        exit(74);
    }

    memset(buf, 0, length + 1);
    readBytes = fread(buf, 1, length, fp);
    if (readBytes < length) {
        fprintf(stderr, "Cannot read file: %s\n", filepath);
        exit(74);
    }

    if (!fclose(fp)) {
        return buf;
    }

    fr(buf);
    fprintf(stderr, "Error opening or reading file %s\n", filepath);
    return NULL;
}

//no char* read_line(const char* prompt)
//no {
//no     int size = sizeof(char) * LINEBUFSIZE;
//no     char* line = (char*)alloc(size);
//no     memset((void*)line, 0, size);
//no     printf("%s", prompt);
//no     fflush(stdin);
//no     fgets(line, size, stdin);
//no     return line;
//no }

//no void run_treewalk_chunk(const char* code)
//no {
//no     interp(code);
//no }

//no void run_treewalk_file(const char* code)
//no {
//no     env_init_global();
//no     run_treewalk_chunk(code);
//no     env_destroy(&GlobalExecutionEnvironment);
//no }

//void run_vm_chunk(const char* code)
//{
//    vm_interpret(code);
//}

void run_vm_file(const char* code)
{
    VmInterpretResult result;

    vm_init();
    result = vm_interpret(code);
    vm_free();

    if (result == INTERPRET_COMPILE_ERROR) {
        exit(65);
    }

    if (result == INTERPRET_RUNTIME_ERROR) {
        exit(70);
    }

    //不要输入任意键返回
    //getchar();
}
